/*
  This file is part of bnc.

  bnc is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  bnc is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with bnc.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "./node.h"

void nodeConstructor (node* aNode, char aValue)
{
  /*
    Create a node.
  */
  aNode->pValue=aValue;
  aNode->pWeight=0;
  aNode->pChildL=0;
  aNode->pChildR=0;
}

unsigned char nodeCountChildren (node* aNode)
{
  /*
    Tell me how many children are there.
  */
  if ((node*)aNode->pChildR!=0) return 2;
  if ((node*)aNode->pChildL!=0) return 1;
  return 0;
}

void nodeInjectChild (node* aNode, node* aChild)
{
  /*
    Adopt a child.
  */
  char i=nodeCountChildren(aNode);

  if (i==1) aNode->pChildR=aChild;
    else if (i==0) aNode->pChildL=aChild;
}

node* nodeJoin (node* aNode, node* aChild)
{
  /*
    Make a family, create a parent.
  */
  node* lPar=(node*)malloc(sizeof(node));
  nodeConstructor(lPar, 0);

  nodeSetWeight(lPar, aNode->pWeight+nodeGetWeight(aChild));
  nodeInjectChild(lPar, aChild);
  nodeInjectChild(lPar, aNode);

  return lPar;
}

node* nodeGetChildL (node* aNode)
{
  /*
    Tell me who was the first child.
  */
  return (node*)aNode->pChildL;
}

node* nodeGetChildR (node* aNode)
{
  /*
    Tell me who was the second child.
  */
  return (node*)aNode->pChildR;
}

char nodeIsLeaf (node* aNode)
{
  /*
    Tell me whether this is a leaf or it is not.
  */
  if (aNode->pChildL==0) return 1; else return 0;  //No left child equals no children at all, equals being a leaf
}

unsigned char nodeGetValue (node* aNode)
{
  /*
    Tell me what value it has.
  */
  return aNode->pValue;
}

unsigned int nodeGetWeight (node* aNode)
{
  /*
    Tell me what weight it has.
  */
  return aNode->pWeight;
}

void nodeSetWeight (node* aNode, unsigned int aWeight)
{
  /*
    Give it a weight.
  */
  aNode->pWeight=aWeight;
}

char nodeSearch (node* aNode, char aValue, unsigned int* aPhase, char* aBufferO)
{
  /*
    Write a bitmap way to the given byte in our stack.

    Move throughout the tree recursively.
    Every time you get to leaf compare its value with the given value.
    Zeros written into buffer indicate taking left edge.
    Ones indicate taking right edge.
  */
  if (aNode->pChildL==0)
  {
    if (aNode->pValue==aValue) return 1; else return 0;
  } else {
    char lFound;

    (*aPhase)++;
    aBufferO[(*aPhase)/8]&=255-(128>>((*aPhase)&7));  //Writting zero at current position.

    lFound=nodeSearch(aNode->pChildL, aValue, aPhase, aBufferO);  //Taking left edge.
    if (lFound==1) return 1;

    aBufferO[(*aPhase)/8]|=128>>((*aPhase)&7);  //Writing one at current position.

    lFound=nodeSearch(aNode->pChildR, aValue, aPhase, aBufferO);  //Taking right edge.
    if (lFound==1) return 1;

    (*aPhase)--;  //Value was not found in this branch.
    return 0;
  }
}
